from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session, joinedload
from sqlalchemy import and_, or_, func, desc

from app.core.database import get_db
from app.models.user import User
from app.models.project import Project, ProjectComment, ProjectStatus
from app.models.team import Team, TeamMember
from app.models.competition import Competition
from app.schemas.project import (
    ProjectCreate, ProjectUpdate, ProjectResponse, ProjectList,
    ProjectCommentCreate, ProjectCommentResponse
)
from app.api.v1.endpoints.auth import get_current_active_user

router = APIRouter()


@router.post("/", response_model=ProjectResponse)
async def create_project(
    project_data: ProjectCreate,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
):
    """创建项目"""
    # 检查竞赛是否存在
    competition = db.query(Competition).filter(Competition.id == project_data.competition_id).first()
    if not competition:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Competition not found"
        )
    
    # 如果指定了团队，检查用户是否是团队成员
    if project_data.team_id:
        team = db.query(Team).filter(Team.id == project_data.team_id).first()
        if not team:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND,
                detail="Team not found"
            )
        
        # 检查用户是否是团队成员
        team_member = db.query(TeamMember).filter(
            and_(
                TeamMember.team_id == project_data.team_id,
                TeamMember.user_id == current_user.id,
                TeamMember.status == "active"
            )
        ).first()
        
        if not team_member:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You are not a member of this team"
            )
    
    # 检查用户是否已经在该竞赛中有项目
    existing_project = db.query(Project).filter(
        and_(
            Project.competition_id == project_data.competition_id,
            Project.created_by == current_user.id,
            Project.status != ProjectStatus.DELETED
        )
    ).first()
    
    if existing_project:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="You already have a project in this competition"
        )
    
    # 创建项目
    project = Project(
        title=project_data.title,
        description=project_data.description,
        competition_id=project_data.competition_id,
        team_id=project_data.team_id,
        created_by=current_user.id,
        repository_url=project_data.repository_url,
        demo_url=project_data.demo_url,
        documentation_url=project_data.documentation_url,
        tech_stack=project_data.tech_stack,
        tags=project_data.tags,
        status=ProjectStatus.DRAFT
    )
    
    db.add(project)
    db.commit()
    db.refresh(project)
    
    return project


@router.get("/", response_model=List[ProjectList])
async def get_projects(
    competition_id: Optional[int] = Query(None, description="竞赛ID"),
    team_id: Optional[int] = Query(None, description="团队ID"),
    status: Optional[str] = Query(None, description="项目状态"),
    tech_stack: Optional[List[str]] = Query(None, description="技术栈"),
    tags: Optional[List[str]] = Query(None, description="标签"),
    search: Optional[str] = Query(None, description="搜索关键词"),
    sort_by: str = Query("created_at", description="排序字段: created_at, score, views"),
    order: str = Query("desc", description="排序方向: asc, desc"),
    page: int = Query(1, ge=1, description="页码"),
    size: int = Query(20, ge=1, le=100, description="每页数量"),
    db: Session = Depends(get_db)
):
    """获取项目列表"""
    query = db.query(Project).filter(Project.status != ProjectStatus.DELETED)
    
    # 竞赛筛选
    if competition_id:
        query = query.filter(Project.competition_id == competition_id)
    
    # 团队筛选
    if team_id:
        query = query.filter(Project.team_id == team_id)
    
    # 状态筛选
    if status:
        query = query.filter(Project.status == status)
    
    # 技术栈筛选
    if tech_stack:
        for tech in tech_stack:
            query = query.filter(Project.tech_stack.contains([tech]))
    
    # 标签筛选
    if tags:
        for tag in tags:
            query = query.filter(Project.tags.contains([tag]))
    
    # 搜索
    if search:
        search_filter = or_(
            Project.title.ilike(f"%{search}%"),
            Project.description.ilike(f"%{search}%")
        )
        query = query.filter(search_filter)
    
    # 排序
    if sort_by == "score":
        order_field = Project.score
    elif sort_by == "views":
        order_field = Project.views
    else:
        order_field = Project.created_at
    
    if order == "desc":
        query = query.order_by(desc(order_field))
    else:
        query = query.order_by(order_field)
    
    # 分页
    offset = (page - 1) * size
    projects = query.offset(offset).limit(size).all()
    
    return projects


@router.get("/{project_id}", response_model=ProjectResponse)
async def get_project(
    project_id: int,
    db: Session = Depends(get_db)
):
    """获取项目详情"""
    project = db.query(Project).options(
        joinedload(Project.competition),
        joinedload(Project.team),
        joinedload(Project.creator)
    ).filter(
        and_(
            Project.id == project_id,
            Project.status != ProjectStatus.DELETED
        )
    ).first()
    
    if not project:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Project not found"
        )
    
    # 增加浏览次数
    project.views += 1
    db.commit()
    
    return project


@router.put("/{project_id}", response_model=ProjectResponse)
async def update_project(
    project_id: int,
    project_update: ProjectUpdate,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
):
    """更新项目"""
    project = db.query(Project).filter(Project.id == project_id).first()
    if not project:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Project not found"
        )
    
    # 检查权限（项目创建者或团队成员可以更新）
    can_update = project.created_by == current_user.id
    
    if project.team_id and not can_update:
        team_member = db.query(TeamMember).filter(
            and_(
                TeamMember.team_id == project.team_id,
                TeamMember.user_id == current_user.id,
                TeamMember.status == "active"
            )
        ).first()
        can_update = team_member is not None
    
    if not can_update:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Permission denied"
        )
    
    # 更新项目信息
    update_data = project_update.dict(exclude_unset=True)
    for field, value in update_data.items():
        setattr(project, field, value)
    
    db.commit()
    db.refresh(project)
    return project


@router.delete("/{project_id}")
async def delete_project(
    project_id: int,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
):
    """删除项目"""
    project = db.query(Project).filter(Project.id == project_id).first()
    if not project:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Project not found"
        )
    
    # 检查权限（只有项目创建者可以删除）
    if project.created_by != current_user.id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Only project creator can delete the project"
        )
    
    # 软删除项目
    project.status = ProjectStatus.DELETED
    db.commit()
    
    return {"message": "Project deleted successfully"}


@router.post("/{project_id}/submit")
async def submit_project(
    project_id: int,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
):
    """提交项目"""
    project = db.query(Project).filter(Project.id == project_id).first()
    if not project:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Project not found"
        )
    
    # 检查权限
    can_submit = project.created_by == current_user.id
    
    if project.team_id and not can_submit:
        team_member = db.query(TeamMember).filter(
            and_(
                TeamMember.team_id == project.team_id,
                TeamMember.user_id == current_user.id,
                TeamMember.status == "active"
            )
        ).first()
        can_submit = team_member is not None
    
    if not can_submit:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Permission denied"
        )
    
    # 检查项目是否可以提交
    if project.status == ProjectStatus.SUBMITTED:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Project already submitted"
        )
    
    # 检查必要字段
    if not project.title or not project.description:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Project title and description are required"
        )
    
    # 提交项目
    project.status = ProjectStatus.SUBMITTED
    project.submitted_at = func.now()
    
    db.commit()
    
    return {"message": "Project submitted successfully"}


@router.post("/{project_id}/comments", response_model=ProjectCommentResponse)
async def create_comment(
    project_id: int,
    comment_data: ProjectCommentCreate,
    current_user: User = Depends(get_current_active_user),
    db: Session = Depends(get_db)
):
    """创建项目评论"""
    project = db.query(Project).filter(
        and_(
            Project.id == project_id,
            Project.status != ProjectStatus.DELETED
        )
    ).first()
    
    if not project:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Project not found"
        )
    
    # 创建评论
    comment = ProjectComment(
        project_id=project_id,
        user_id=current_user.id,
        content=comment_data.content,
        parent_id=comment_data.parent_id
    )
    
    db.add(comment)
    db.commit()
    db.refresh(comment)
    
    return comment


@router.get("/{project_id}/comments", response_model=List[ProjectCommentResponse])
async def get_comments(
    project_id: int,
    page: int = Query(1, ge=1, description="页码"),
    size: int = Query(20, ge=1, le=100, description="每页数量"),
    db: Session = Depends(get_db)
):
    """获取项目评论"""
    project = db.query(Project).filter(
        and_(
            Project.id == project_id,
            Project.status != ProjectStatus.DELETED
        )
    ).first()
    
    if not project:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Project not found"
        )
    
    # 获取顶级评论
    query = db.query(ProjectComment).options(
        joinedload(ProjectComment.user)
    ).filter(
        and_(
            ProjectComment.project_id == project_id,
            ProjectComment.parent_id.is_(None)
        )
    ).order_by(desc(ProjectComment.created_at))
    
    # 分页
    offset = (page - 1) * size
    comments = query.offset(offset).limit(size).all()
    
    return comments


@router.get("/stats/overview")
async def get_projects_stats(
    competition_id: Optional[int] = Query(None, description="竞赛ID"),
    db: Session = Depends(get_db)
):
    """获取项目统计数据"""
    query = db.query(Project).filter(Project.status != ProjectStatus.DELETED)
    
    if competition_id:
        query = query.filter(Project.competition_id == competition_id)
    
    total_projects = query.count()
    submitted_projects = query.filter(Project.status == ProjectStatus.SUBMITTED).count()
    draft_projects = query.filter(Project.status == ProjectStatus.DRAFT).count()
    
    # 获取热门技术栈
    tech_stack_stats = db.query(
        func.unnest(Project.tech_stack).label('tech'),
        func.count().label('count')
    ).filter(
        Project.status != ProjectStatus.DELETED
    ).group_by('tech').order_by(desc('count')).limit(10).all()
    
    stats = {
        "total_projects": total_projects,
        "submitted_projects": submitted_projects,
        "draft_projects": draft_projects,
        "popular_tech_stack": [{"name": tech, "count": count} for tech, count in tech_stack_stats]
    }
    
    return stats